home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / huffman2.zip / DECODER.BAS < prev    next >
BASIC Source File  |  1992-06-01  |  4KB  |  160 lines

  1. 'Huffman decoder
  2. 'by Rich Geldreich May 29th, 1992
  3. 'This program is in the public domain.
  4. DEFINT A-Z
  5.  
  6. DECLARE FUNCTION GetBit ()
  7. DECLARE SUB FillBuff ()
  8.  
  9. CONST True = -1, False = 0
  10. CONST Null = -2
  11. CONST BufferLength = 10000
  12.  
  13. DIM SHARED Bits(8)
  14. DIM SHARED Father(512)
  15. DIM SHARED LeftSon(512)
  16. DIM SHARED RightSon(512)
  17.  
  18. DIM SHARED Buffer$, Address, EndAddress, CurrentByte, BitsIn, BufferSeg
  19.  
  20. Bits:
  21.     DATA 1,2,4,8,16,32,64,128,256
  22.  
  23. RESTORE Bits
  24. FOR A = 0 TO 8: READ Bits(A): NEXT
  25. 'disk buffer
  26. Buffer$ = STRING$(BufferLength, 0): EndAddress = 1: Address = 0: BitsIn = -1
  27. 'turn on cursor
  28. LOCATE , , 1
  29. 'open the compressed file
  30. OPEN "output.huf" FOR BINARY AS #1
  31. 'get the header
  32. GET #1, , FileLength&
  33. GET #1, , RealIndex
  34. GET #1, , TopOfTree
  35. 'read in the tree
  36. FOR A = 0 TO RealIndex
  37.     IF GetBit THEN
  38.         Father = 0
  39.         FOR C = 0 TO 7
  40.             IF GetBit THEN Father = Father + Bits(C)
  41.         NEXT
  42.         Father(A) = Father
  43.         RightSon(A) = Null
  44.         LeftSon(A) = Null
  45.     ELSE
  46.         Father(A) = 256
  47.         IF GetBit THEN
  48.             Son = 0
  49.             FOR C = 0 TO 8
  50.                 IF GetBit THEN Son = Son + Bits(C)
  51.             NEXT
  52.             LeftSon(A) = Son
  53.         ELSE
  54.             LeftSon(A) = Null
  55.         END IF
  56.         IF GetBit THEN
  57.             Son = 0
  58.             FOR C = 0 TO 8
  59.                 IF GetBit THEN Son = Son + Bits(C)
  60.             NEXT
  61.             RightSon(A) = Son
  62.         ELSE
  63.             RightSon(A) = Null
  64.         END IF
  65.     END IF
  66. NEXT
  67. 'when PrintCounter=1024 then screen is updated
  68. PrintCounter = 0
  69. 'A$ is the output buffer
  70. A$ = STRING$(5000, 0)
  71. A& = SADD(A$)
  72. A& = A& - 65536 * (A& < 0)
  73. OutputSeg = VARSEG(A$) + (A& \ 16)
  74. OAddress = (A& MOD 16)
  75. OEndAddress = OAddress + 5000
  76. OStart = OAddress
  77. 'start decoding
  78. PRINT "Decoding:";
  79. Xpos = POS(0): Ypos = CSRLIN
  80. 'open output file
  81. OPEN COMMAND$ FOR BINARY AS #2
  82. 'decode each byte
  83. FOR CurrentByte& = 1 TO FileLength&
  84.     DEF SEG = BufferSeg
  85.     'start at top of tree
  86.     A = TopOfTree
  87.     'keep on getting bits until a character is found
  88.     DO
  89.         'if BitsIn<0 then time to fill byte buffer
  90.         IF BitsIn < 0 THEN
  91.             Address = Address + 1
  92.             'if Address=EndBuffer then time to fill disk buffer
  93.             IF Address = EndAddress THEN
  94.                 FillBuff
  95.             END IF
  96.             CurrentByte = PEEK(Address): BitsIn = 7
  97.         END IF
  98.         'see if we go left or right
  99.         IF (CurrentByte AND Bits(BitsIn)) THEN A = LeftSon(A) ELSE A = RightSon(A)
  100.         BitsIn = BitsIn - 1
  101.         F = Father(A)
  102.         'loop until an ascii character is found
  103.     LOOP UNTIL F < 256
  104.     'put byte into output buffer
  105.     DEF SEG = OutputSeg
  106.     POKE OAddress, F
  107.     OAddress = OAddress + 1
  108.     IF OAddress = OEndAddress THEN
  109.         PUT #2, , A$
  110.         A& = SADD(A$)
  111.         A& = A& - 65536 * (A& < 0)
  112.         OutputSeg = VARSEG(A$) + (A& \ 16)
  113.         OAddress = (A& MOD 16)
  114.         OEndAddress = OAddress + 5000
  115.         OStart = OAddress
  116.     END IF
  117.     'see if time to update the screen
  118.     PrintCounter = PrintCounter + 1
  119.     IF PrintCounter = 1024 THEN
  120.         PrintCounter = 0
  121.         LOCATE Ypos, Xpos
  122.         PRINT (CurrentByte& * 100) \ FileLength&; "%";
  123.     END IF
  124. 'loop until all of the characters have been restored
  125. NEXT
  126. 'save whatever is currently in the output buffer
  127. A$ = LEFT$(A$, OAddress - OStart)
  128. PUT #2, , A$
  129. CLOSE
  130. 'all done
  131. LOCATE Ypos, Xpos
  132. PRINT " done."
  133.  
  134. END
  135.  
  136. 'fills the input buffer
  137. SUB FillBuff
  138.     GET #1, , Buffer$
  139.     A& = SADD(Buffer$)
  140.     A& = A& - 65536 * (A& < 0)
  141.     BufferSeg = VARSEG(Buffer$) + (A& \ 16)
  142.     Address = (A& MOD 16)
  143.     EndAddress = Address + BufferLength
  144.     DEF SEG = BufferSeg
  145. END SUB
  146.  
  147. 'gets one bit from the input file(only used when the tree
  148. 'is read in)
  149. FUNCTION GetBit STATIC
  150.     IF BitsIn < 0 THEN
  151.         Address = Address + 1
  152.         IF Address = EndAddress THEN
  153.             FillBuff
  154.         END IF
  155.         CurrentByte = PEEK(Address): BitsIn = 7
  156.     END IF
  157.     GetBit = (CurrentByte AND Bits(BitsIn)): BitsIn = BitsIn - 1
  158. END FUNCTION
  159.  
  160.